from datetime import date
from django.db.models import F, Q, Sum, Avg, Min, Count, Max


from django.shortcuts import render

# Create your views here.
# 导入模型
from booktest.models import BookInfo, HeroInfo

"""增加数据 save和create"""
book = BookInfo()
book.btitle = '西游记'
book.bpub_data = '1763-7-1'
book.save()

hero1 = HeroInfo(
    hname='孙悟空',
    hgender=0,
    # hbook_id=book.id,
    hbook=book  # 这样写相当于外键直接关联到book这个对象上,不能hbook=book.id

)
hero1.save()

# create 写法 在创建模型赋值的时候就已经存储了  不用写save（）
book2 = BookInfo.objects.create(
    btitle='梦三国',
    bpub_data='2011-11-11',
    bread=10,
    bcomment=7
)

# 基本查询 get all count

BookInfo.objects.get(id=1)
BookInfo.objects.all()
BookInfo.objects.count()

# 过滤查询
# filter 过滤除多个结果
# exclude 排除掉符合条件剩下的结果
# get 过滤单一结果
# 过滤条件的表达语法如下：属性名称__比较运算符=值

# 2.查询书名包含‘湖’的书籍
BookInfo.objects.filter(btitle__contains='湖')

# 3.查询书名以‘部’结尾的书籍
BookInfo.objects.filter(btitle__endswith='部')

# 4.查询书名不为空的书籍
BookInfo.objects.filter(btitle__isnull=False)

# 5.查询编号为2或4的书籍
BookInfo.objects.filter(id__in=[2, 4])

# 6.查询编号大于2的书籍
BookInfo.objects.filter(id__gt=2)

# 7.查询id不等于3的书籍
BookInfo.objects.exclude(id=3)

# 8.查询1980年发表的书籍
BookInfo.objects.filter(bpub_data__year=1980)

# 9.查询1990年1月1日后发表的书籍
BookInfo.objects.filter(bpub_data__gt=date(1990, 1, 1))
BookInfo.objects.filter(bpub_data__gt='1991-1-1')
# F对象  适用于两个以上属性的比较
# 语法如下： F(属性名)
# 1.查询阅读量大于评论量的书籍
BookInfo.objects.filter(bread__gt=F('bcomment'))
# 2.查询阅读量大于2倍评论量的书籍
BookInfo.objects.filter(bread__gt=F('bcomment') * 2)

# Q对象
# 多个过滤器逐个调用表示逻辑与关系，同sql语句中where部分的and关键字
# 查询阅读量大于20，并且编号小于3的图书。
BookInfo.objects.filter(bread__gt=20, id__lt=3)
# 1.查询阅读量大于20，或编号小于3的图书
BookInfo.objects.filter(Q(bread__gt=20), Q(id__lt=3))
# 2.查询编号不等于3的书籍 Q对象前可以使用~操作符，表示非not。
BookInfo.objects.filter(~Q(pk=3))

# 聚合函数
# 使用aggregate()过滤器调用聚合函数。
# aggregate 查询返回的是字典  count返回的是数字
# 聚合函数包括：Avg 平均，Count 数量，Max 最大，Min 最小，Sum 求和，
# 使用count时一般不使用aggregate()过滤器。
# 被定义在django.db.models中。
# 1.统计总的阅读量
BookInfo.objects.aggregate(Sum('bread'))
# BookInfo.objects.aggregate(Count('bread'))  返回6  count多用于对象的数数
# 例：查询图书总数。
BookInfo.objects.count()

"""排序"""
# order_by
BookInfo.objects.all().order_by('bread')
BookInfo.objects.all().order_by("-bread")

"""关联查询"""
# 1.一查多：查询编号为1的图书中所有人物信息
# 由一到多的访问语法：
# 一对应的模型类对象.多对应的模型类名小写_set
b = BookInfo.objects.get(id=1)  # 先查询编号为1 的书
b.heroinfo_set.all()
BookInfo.objects.get(id=1).heroinfo_set.all()  # heroinfo_set 这是一个隐藏的外键，由于在英雄模型
# 定义了一个hbook外键  所以 产生heroinfo_set 这个外键
# 由多到一的访问语法:
# 多对应的模型类对象.多对应的模型类中的关系类属性名
# 2.多查一：查询编号为1的英雄出自的书籍
hero2 = HeroInfo.objects.get(id=1)
hero2.hbook

# HeroInfo.objects.get(id=1).hbook

"""关联过滤查询"""
# 1.多查一：查询书籍中人物的描述包含"降龙"的书籍
# 语法如下：
# 关联模型类名小写__属性名__条件运算符=值
BookInfo.objects.filter(heroinfo__hcomment__contains='降龙')

# 2.一查多：查询书名为"天龙八部"的所有人物信息
# 一模型类关联属性名__一模型类属性名__条件运算符=值
HeroInfo.objects.filter(hbook__btitle="天龙八部")  # 通过外键的字段来查询  外键的字段就表示关联的书名
# 查询图书阅读量大于30的所有英雄
HeroInfo.objects.filter(hbook__bread__gt=30)

"""修改"""
# 修改更新有两种方法
# 1.save
book3 = BookInfo.objects.get(btitle='西游记')
book3.btitle = "西游记后传"
book3.save()

# 2.updata
BookInfo.objects.filter(btitle='梦三国').update(btitle='梦三国2')  # 返回被修改的对象数

"""删除"""
# 删除有两种方法
# 1.模型类对象delete
book4 = BookInfo.objects.get(id=6)
book4.delete()

BookInfo.objects.get(id=5).delete()

"""查询集"""
# 3. 限制查询集  就是切片   限制查询到多少
qs = BookInfo.objects.all()[0:2]
